package com.spdb.oa.util;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathExpressionException;

import org.json.JSONObject;
import org.xml.sax.SAXException;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.spdb.oa.OAService;
import com.spdb.oa.OAServiceImpl;
import com.spdb.oa.exception.OAException;
import com.spdb.oa.type.Record;
import com.spdb.oa.type.SubmitForm;
import com.spdb.oa.type.Toolbar;
import com.spdb.oa.type.User;
import com.spdb.oa.type.UserListCount;
import com.spdb.oa.type.WFForm;
import com.spdb.oa.type.WorkflowOpinion;

public class OAJsonUtil {
	
	Logger logger = Logger.getLogger(OAJsonUtil.class.getName());
	
	private ObjectMapper mapper;
	static private OAJsonUtil otj;
	
	public OAJsonUtil() {
		this.mapper = new ObjectMapper();
	}
	
	public String getWFFormJson(WFForm wfForm) throws OAException {
		Map<String, Object> returnMap = new HashMap<String, Object>();

		try {
			returnMap.put(OAConstants.WF_FORM, wfForm);
			returnMap.put(OAConstants.STATUS_KEY, OAConstants.STATUS_OK);
			return mapper.writeValueAsString(returnMap);
		} catch (JsonProcessingException e) {
			logger.severe("OA java data to Json error: " + e.getMessage());
			throw new OAException(e);
		}
	}
	
	
	public String getSubmitWFJson(JSONObject obj) {
		return jSONObjectToString(obj);
	}
	
	public String getWorkflowOpinionJson(WorkflowOpinion obj) throws OAException {
		Map<String, Object> returnMap = new HashMap<String, Object>();

		try {
			ObjectNode jsonNode = (ObjectNode) mapper.convertValue(obj, JsonNode.class);			
			jsonNode.put(OAConstants.STATUS_KEY, OAConstants.STATUS_OK);
			return mapper.writeValueAsString(jsonNode);
		} catch (JsonProcessingException e) {
			logger.severe("OA java data to Json error: " + e.getMessage());
			throw new OAException(e.getMessage());
		}
	}

	private String jSONObjectToString(JSONObject obj) {
		obj.put(OAConstants.STATUS_KEY, OAConstants.STATUS_OK);
		return obj.toString();
	}
	
	public String getToolbarJson(Toolbar toolbar) throws OAException {
		Map<String, Object> returnMap = new HashMap<String, Object>();
		
		try {
				returnMap.put(OAConstants.TOOLBAR, toolbar);
				returnMap.put(OAConstants.STATUS_KEY, OAConstants.STATUS_OK);
				return mapper.writeValueAsString(returnMap);
			} catch (JsonProcessingException e) {
				logger.severe("OA java data to Json error: " + e.getMessage());
				throw new OAException(e);
		}
		
	}
	
	public String getSubmitJson(SubmitForm sf) throws OAException {
		Map<String, Object> returnMap = new HashMap<String, Object>();
		
		try {
			returnMap.put(OAConstants.SUBMIT_FORM, sf);
			returnMap.put(OAConstants.STATUS_KEY, OAConstants.STATUS_OK);
			return mapper.writeValueAsString(returnMap);
		} catch (JsonProcessingException e) {
			logger.severe("OA java data to Json error: " + e.getMessage());
			throw new OAException(e);
		}
	}
	
	public String getListCountJson(Map<User, UserListCount> userListCountMap) throws OAException {
		HashMap<String, Object> returnMap = new HashMap<String, Object>();
		
		Iterator<Map.Entry<User, UserListCount>> iter = userListCountMap.entrySet().iterator();
		if (iter.hasNext()) {
			Map.Entry<User, UserListCount> entry = iter.next();
			returnMap.put("User", entry.getValue());
			returnMap.put("STATUS", "0");
		} else {
			returnMap.put("STATUS", "1");
		}
		
		try {
			return mapper.writeValueAsString(returnMap);
		} catch (JsonProcessingException e) {
			logger.severe("OA java data to Json error: " + e.getMessage());
			throw new OAException(e);
		}
	}
	
	public String getJBListJson(Map<User, List<Record>> records) throws OAException {
		return this.getListJson(records);
	}
	
	public String getDBListJson(Map<User, List<Record>> records) throws OAException {
		return this.getListJson(records);
	}
	
	private String getListJson(Map<User, List<Record>> records) throws OAException {
		Map<String, Object> transformedMap = new HashMap<String, Object>();
		
		Iterator<Map.Entry<User, List<Record>>> iter = records.entrySet().iterator();
		if (iter.hasNext()) {
			Map.Entry<User, List<Record>> entry = iter.next();
			transformedMap.put("User", entry.getValue());
			transformedMap.put("STATUS", "0");
		} else {
			transformedMap.put("STATUS", "1");
		}
		
		try {
			return mapper.writeValueAsString(transformedMap);
		} catch (JsonProcessingException e) {
			logger.severe("OA java data to Json error: " + e.getMessage());
			throw new OAException(e);
		}
	}
	
	public String toJson(Object o) throws OAException {
		try {
			return mapper.writeValueAsString(o);
		} catch (JsonProcessingException e) {
			logger.severe("OA java data to Json error: " + e.getMessage());
			throw new OAException(e);
		}
	}

	static public OAJsonUtil getInstance() {
		if (OAJsonUtil.otj == null) {
			OAJsonUtil.otj = new OAJsonUtil();
		} 
		
		return OAJsonUtil.otj;
		
	}
	
	public static void main(String[] args) throws ParserConfigurationException, XPathExpressionException, IOException, SAXException, OAException {
		OAJsonUtil otj = OAJsonUtil.getInstance();
	
		String processId ="b066fd5d-a314-41d2-9282-a56c953f122a";
		String instanceId = "a93e7050-ef1c-4738-8f95-d849dfef870e";
		String feedbackParameter = "UHJvY2Vzc0lEPWIwNjZmZDVkLWEzMTQtNDFkMi05MjgyLWE1NmM5NTNmMTIyYSZJbnN0YW5jZUlEPWE5M2U3MDUwLWVmMWMtNDczOC04Zjk1LWQ4NDlkZmVmODcwZSZPcGVyYXRpb249RGVhbCZEYXRhVHlwZT1EQiZFeGVjdXRvcklEPTAyZTI0ZTIwLTZlZjItNGNiZC1iMTIzLTVjOGY0M2Y3OTY1NCZiZWRlbGVnYXRvcklkPSZMZWFkZXJJRD0mVXNlcklEPTAyZTI0ZTIwLTZlZjItNGNiZC1iMTIzLTVjOGY0M2Y3OTY1NCZNb2RlbEFsaWFzPU1vZGVsTFhEJlBhcmFtZXRlclNvdXJjZT1HZXRUb29sYmFy";

//		String processId = "3137153e-0bdf-4e2f-b5a8-80a9781df720";
//		String instanceId = "1b83988d-eb3b-4b65-a403-a142f7432ba0";
//		String feedbackParameter = "UGFyYW1ldGVyU291cmNlPUdldERCTGlzdCZQcm9jZXNzSUQ9MzEzNzE1M2UtMGJkZi00ZTJmLWI1YTgtODBhOTc4MWRmNzIwJkluc3RhbmNlSUQ9MWI4Mzk4OGQtZWIzYi00YjY1LWE0MDMtYTE0MmY3NDMyYmEwJk9wZXJhdGlvbj1EZWFsJkRhdGFUeXBlPURCJkV4ZWN1dG9ySUQ9MDJlMjRlMjAtNmVmMi00Y2JkLWIxMjMtNWM4ZjQzZjc5NjU0JmJlZGVsZWdhdG9ySWQ9JkxlYWRlcklEPSZVc2VySUQ9MDJlMjRlMjAtNmVmMi00Y2JkLWIxMjMtNWM4ZjQzZjc5NjU0Jk1vZGVsQWxpYXM9TW9kZWxXWkNMRlc=";
//		String processId = "b066fd5d-a314-41d2-9282-a56c953f122a";
//		String instanceId = "a93e7050-ef1c-4738-8f95-d849dfef870e";
//		String feedbackParameter = "UGFyYW1ldGVyU291cmNlPUdldERCTGlzdCZQcm9jZXNzSUQ9YjA2NmZkNWQtYTMxNC00MWQyLTkyODItYTU2Yzk1M2YxMjJhJkluc3RhbmNlSUQ9YTkzZTcwNTAtZWYxYy00NzM4LThmOTUtZDg0OWRmZWY4NzBlJk9wZXJhdGlvbj1EZWFsJkRhdGFUeXBlPURCJkV4ZWN1dG9ySUQ9MDJlMjRlMjAtNmVmMi00Y2JkLWIxMjMtNWM4ZjQzZjc5NjU0JmJlZGVsZWdhdG9ySWQ9JkxlYWRlcklEPSZVc2VySUQ9MDJlMjRlMjAtNmVmMi00Y2JkLWIxMjMtNWM4ZjQzZjc5NjU0Jk1vZGVsQWxpYXM9TW9kZWxMWEQ=";
	
//		String processId = "5df30314-adfb-48e3-9b82-882e196a8301";
//		String instanceId = "ba9e4920-6aa6-46cc-9c12-7d1ce09e7189";
//		String feedbackParameter = "UHJvY2Vzc0lEPTVkZjMwMzE0LWFkZmItNDhlMy05YjgyLTg4MmUxOTZhODMwMSZJbnN0YW5jZUlEPWJhOWU0OTIwLTZhYTYtNDZjYy05YzEyLTdkMWNlMDllNzE4OSZPcGVyYXRpb249RGVhbCZEYXRhVHlwZT1EQiZFeGVjdXRvcklEPTJlZDRkMzBkLTQ2NjktNDk0OC04NmMxLTRkMWFjMDdhZDRjMyZiZWRlbGVnYXRvcklkPSZMZWFkZXJJRD0mVXNlcklEPTJlZDRkMzBkLTQ2NjktNDk0OC04NmMxLTRkMWFjMDdhZDRjMw==";
	
//		String processId = "29f9ab7c-061c-430f-a71e-d586fbe69c2f";
//		String instanceId = "4eca4f20-884f-4637-8c83-dce052331ac4";
//		String feedbackParameter = "UHJvY2Vzc0lEPTI5ZjlhYjdjLTA2MWMtNDMwZi1hNzFlLWQ1ODZmYmU2OWMyZiZJbnN0YW5jZUlEPTRlY2E0ZjIwLTg4NGYtNDYzNy04YzgzLWRjZTA1MjMzMWFjNCZPcGVyYXRpb249VmlldyZEYXRhVHlwZT1KQiZFeGVjdXRvcklEPTJlZDRkMzBkLTQ2NjktNDk0OC04NmMxLTRkMWFjMDdhZDRjMyZVc2VySUQ9MmVkNGQzMGQtNDY2OS00OTQ4LTg2YzEtNGQxYWMwN2FkNGMzJk1vZGVsQWxpYXM9TW9kZWxMWEQmQ3VycmVudFN0ZXBOYW1lPeWPkei1t+mDqOmXqOWGhemDqOa1gei9rCZQYXJhbWV0ZXJTb3VyY2U9R2V0SkJMaXN0JmJlZGVsZWdhdG9ySWQ9JkxlYWRlcklEPQ==";
	
		
		OAService service = new OAServiceImpl();
		WFForm wfForm = service.getWFForm(processId, instanceId, "0", feedbackParameter);
//		Map<User, List<Record>> map = OAXMLParser.testJBList();
//		Map<User, UserListCount> listCountMap = service.getListCount();
//		Map<User, List<Record>> jbMap = service.getJBList(10, 1);
//		Map<User, List<Record>> dbMap = service.getDBList(10, 1);
//		SubmitForm sf = service.getSubmit(processId, instanceId, "0", feedbackParameter);
		
	
//		Toolbar toolbar;
//		try {
//			toolbar = service.getToolbar(processId, instanceId, "0", feedbackParameter);
//			String toolbarJson = OAJsonUtil.getInstance().getToolbarJson(toolbar);
//			System.out.println(toolbarJson);
//		} catch (OAException e) {
//			System.out.println(e.oaMessage);
//		}
		
//		String listCountJson = otj.toJson(listCountMap);
//		String jbJson = otj.toJson(jbMap);
//		String dbJson = otj.toJson(dbMap);
//		System.out.println(listCountJson);
//		System.out.println("DB List:");
//		System.out.println(dbJson);
		
//		System.out.println(jbJson);
		
//		String submitFormJson = otj.getSubmitJson(sf);
//		System.out.println("SubmitFormJson:");
//		System.out.println(submitFormJson);
//		
//		String selfListCountJson = OAJsonUtil.getInstance().getListCountJson(OAUserUtil.selectSelfListCount(listCountMap));
//		System.out.println(selfListCountJson);
//		String selfJBListJson = OAJsonUtil.getInstance().getJBListJson(OAUserUtil.selectSelfList(jbMap));
//		System.out.println(selfJBListJson);
//		String selfDBListJson = OAJsonUtil.getInstance().getDBListJson(OAUserUtil.selectSelfList(dbMap));
//		System.out.println(selfDBListJson);

		
//		WorkflowOpinion obj = service.getWorkFlowOpinion(processId, instanceId, "0", feedbackParameter);
//		String workflowOpinionJson = OAJsonUtil.getInstance().getWorkflowOpinionJson(obj);
//		System.out.println("Workflow Opinion Json:");
//		System.out.println(workflowOpinionJson);
//		
		String wfFormJson = OAJsonUtil.getInstance().getWFFormJson(wfForm);
		System.out.println("WFForm Json:");
		System.out.println(wfFormJson);
		
	}
	
}
